﻿/***************************
 * Author：peiyang
 * DateTime：
 * Description：<Description>
 * Copyright：臭皮匠工作室@2020
 **/

using System;
using System.Collections.Generic;
using System.Text;
using Cpjit.SunnyPaine.Toolkit.RabbitMQ.Enums;
using Cpjit.SunnyPaine.Toolkit.RabbitMQ.Model;

namespace Cpjit.SunnyPaine.Toolkit.RabbitMQ
{
    /// <summary>
    /// 提供RabbitMQ客户端工具的接口
    /// </summary>
    public interface IRabbitmqClient
    {
        #region 属性定义
        /// <summary>
        /// RabbitMQ的主机名或远程IP地址。
        /// </summary>
        string HostName { get; set; }

        /// <summary>
        /// 端口号
        /// </summary>
        int Port { get; set; }

        /// <summary>
        /// 用户名。
        /// </summary>
        string UserName { get; set; }

        /// <summary>
        /// 密码。
        /// </summary>
        string Password { get; set; }

        /// <summary>
        /// 客户端唯一标识。
        /// </summary>
        string ClientId { get; set; }

        /// <summary>
        /// 消息编码。默认 System.Text.Encoding.Default 。
        /// </summary>
        Encoding Encoding { get; set; }

        /// <summary>
        /// 心跳检测周期。单位：秒。
        /// </summary>
        ushort? RequestedHeartbeat { get; set; }

        /// <summary>
        /// 是否处于已连接可用状态。
        /// </summary>
        bool IsConnected { get; }
        #endregion


        #region 委托定义
        /// <summary>
        /// 当与RabbitMQ连接状态变化时发生。
        /// </summary>
        event Action<IRabbitmqClient, StatusEventArgs> ConnectionStatusChanged;

        /// <summary>
        /// 当出现错误时发生。
        /// <para>IRabbitmqClient：RabbitMQ客户端对象。ExceptionEventArgs：异常信息。bool：是否可用于UI操作。</para>
        /// </summary>
        event Action<IRabbitmqClient, ExceptionEventArgs, bool> Error;
        #endregion


        #region 方法定义
        /// <summary>
        /// 连接RabbitMQ一次。如果连接失败，不会自动重连。
        /// </summary>
        bool ConnectOnce();

        /// <summary>
        /// 连接RabbitMQ。如果第一次连接尝试失败，将执行重连尝试。
        /// </summary>
        bool Connect();

        /// <summary>
        /// 异步连接RabbitMQ。
        /// </summary>
        /// <param name="dlls">包含实现了IConsumer接口的消费者类的程序集。</param>
        /// <param name="autoRegisterConsumer">自动注册消费者。</param>
        void AsyncConnect(IEnumerable<string> dlls, bool autoRegisterConsumer = true);

        /// <summary>
        /// 断开连接RabbitMQ。
        /// </summary>
        void Close();

        /// <summary>
        /// 注册消费者。如果使用IConsumer接口注册消费者，则必须调用该接口。
        /// </summary>
        void RegisterConsumer();

        /// <summary>
        /// 注册消费者。如果使用IConsumer接口注册消费者，则必须调用该接口。
        /// </summary>
        /// <param name="dlls">要扫描的目标dll完整路径。</param>
        void RegisterConsumer(IEnumerable<string> dlls);

        /// <summary>
        /// 创建消费者。
        /// </summary>
        /// <param name="consumer">消费者对象。</param>
        void CreateConsumer(IConsumer consumer);

        /// <summary>
        /// 绑定目标。
        /// </summary>
        /// <param name="metaObject"></param>
        /// <param name="handler">目标方法。</param>
        void BindDestination(ConsumerMetaObject metaObject, Action<IRabbitmqClient, DataEventArgs> handler);

        /// <summary>
        /// 发送文本消息。针对 simple/work 消息模式。
        /// </summary>
        /// <param name="text">文本消息。</param>
        /// <param name="queueName">队列名称。</param>
        /// <param name="property">附加属性。可为null。</param>
        void Send(string text, string queueName, BasicProperty property);

        /// <summary>
        /// 发送文本消息。针对基于交换器的消息模式。
        /// </summary>
        /// <param name="text">文本消息。</param>
        /// <param name="mode">工作模式。</param>
        /// <param name="exchangeName">交换器名称。如果工作模式为基于交换器的话。</param>
        /// <param name="routingKey">路由键。如果工作模式为基于交换器的 direct 模式的话。</param>
        /// <param name="property">附加属性。可为null。</param>
        void Send(string text, WorkMode mode, string exchangeName, string routingKey, BasicProperty property);

        /// <summary>
        /// 发送字节数组消息。
        /// </summary>
        /// <param name="data">消息数据。</param>
        /// <param name="mode">工作模式。</param>
        /// <param name="exchangeName">交换器名称。如果工作模式为基于交换器的话。</param>
        /// <param name="queueName">队列名称。</param>
        /// <param name="routingKey">路由键。如果工作模式为基于交换器的 direct 模式的话。</param>
        /// <param name="property">附加属性。可为null。</param>
        void Send(byte[] data, WorkMode mode, string exchangeName, string queueName, string routingKey, BasicProperty property);
        #endregion
    }
}